#include "common.h"

namespace onet
{

    //! Helper functions
    //! Gets the IPv4 / IPv6 adress
    bool getSockAddress6(sockaddr_in6& addr, const SNetworkAddress& netAddr)
    {
        if (!netAddr.IPv6)
            return false;

#ifdef WINDOWS
        int slen = sizeof(addr);

        if (WSAStringToAddressA((CHAR*) netAddr.ip.c_str(), AF_INET6, NULL, (struct sockaddr*)&addr, &slen) != 0)
            return false;

        return true;
#else
        addr.sin6_family = AF_INET6;
        inet_pton(AF_INET6, netAddr.ip.c_str(), &addr.sin6_addr.s6_addr);
        addr.sin6_port = htons(netAddr.portNumber);

        return true;
#endif
    }

    bool getSockAddress(sockaddr_in& addr, const SNetworkAddress& netAddr)
    {
        if (netAddr.IPv6)
            return false;

#ifdef WINDOWS
        int slen = sizeof(addr);

        if (WSAStringToAddressA((CHAR*) netAddr.ip.c_str(), AF_INET, NULL, (struct sockaddr*)&addr, &slen) != 0)
            return false;

        return true;
#else
        addr.sin_family = AF_INET;
        inet_aton(netAddr.ip.c_str(), &addr.sin_addr);
        addr.sin_port = htons(netAddr.portNumber);

        return true;
#endif
    }

    //! The other way around
    bool getNetworkAddress6(const sockaddr_in6& addr, SNetworkAddress& netAddr)
    {
#ifdef WINDOWS
        c8 ipAsString[25];
        DWORD size = 25;

        if(WSAAddressToString((sockaddr*) &addr, sizeof(addr), NULL, &ipAsString[0], &size) != 0)
            return false;

        netAddr.IPv6 = true;
        netAddr.ip = std::string(&ipAsString[0]);
        netAddr.portNumber = ntohs(addr.sin6_port);

        return true;
#else
        c8 ipAsString[25];

        if (inet_ntop( AF_INET6, (in6_addr*) &addr.sin6_addr, &ipAsString[0], 25))
        {
            netAddr.IPv6 = true;
            netAddr.ip = std::string(&ipAsString[0]);
            netAddr.portNumber = ntohs(addr.sin6_port);

            return true;
        }

        return false;
#endif
    }

    bool getNetworkAddress(const sockaddr_in& addr, SNetworkAddress& netAddr)
    {
#ifdef WINDOWS
        c8 ipAsString[16];
        DWORD size = 16;

        if(WSAAddressToString((sockaddr*) &addr, sizeof(addr), NULL, &ipAsString[0], &size) != 0)
            return false;

        netAddr.IPv6 = false;
        netAddr.ip = std::string(&ipAsString[0]);
        netAddr.portNumber = ntohs(addr.sin_port);

        return true;
#else

        c8 ipAsString[16];

        if (inet_ntop( AF_INET, (in_addr*) &addr.sin_addr, &ipAsString[0], 16))
        {
            netAddr.IPv6 = false;
            netAddr.ip = std::string(&ipAsString[0]);
            netAddr.portNumber = ntohs(addr.sin_port);

            return true;
        }

        return false;
#endif
    }

} //!end namespace onet
